/**
 * 
 */
package com.easy.generate.task;

import java.io.File;
import java.net.URISyntaxException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;


/**
 * 
 * @author wy
 * @version v 0.1 2013-6-2 下午1:36:07 wy Exp $
 */
public class TaskUtil {

    /** 日志 */
    private static final Logger              log           = LoggerFactory
                                                               .getLogger(TaskUtil.class);

    /** 参数 */
    private final static Map<String, String> propertiesMap = new LinkedHashMap<String, String>();

    /** 生成任务 */
    private final static Map<String, Task>   taskMap       = new LinkedHashMap<String, Task>();

    private static String[]                  tables        = new String[] {};

    /**
     * 获取生成的表
     * 
     * @return
     */
    public static String[] getTables() {
        return tables;
    }

    /**
     * 获取配置的属性
     * 
     * @return
     */
    public static Map<String, String> getPropertiesmap() {
        return propertiesMap;
    }

    /**
     * 获取任务
     * 
     * @return
     */
    public static Map<String, Task> getTaskmap() {
        return taskMap;
    }

    /**
     * 获取任务列表
     * 
     * @return
     */
    public static void load() {
        String xmlPath = null;
        try {
            xmlPath = Thread.currentThread().getContextClassLoader().getResource("").toURI()
                .getPath();
        }
        catch (URISyntaxException e) {

        }

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        //设置验证
        factory.setValidating(true);
        //由于我们只关心非空白元素，这里再加一条设置：
        //factory.setIgnoringElementContentWhitespace(true);
        DocumentBuilder builder = null;
        try {
            builder = factory.newDocumentBuilder();
        }
        catch (ParserConfigurationException e) {
            throw new RuntimeException("创建xml解析错误", e);
        }
        builder.setErrorHandler(new ErrorHandler() {
            @Override
            public void warning(SAXParseException exception) throws SAXException {
                log.warn("解析xml-warning", exception);
            }

            @Override
            public void error(SAXParseException exception) throws SAXException {
                throw new RuntimeException("解析command.xml错误" + exception.getLineNumber() + "行,"
                                           + exception.getColumnNumber() + "列");
            }

            @Override
            public void fatalError(SAXParseException exception) throws SAXException {
                log.warn("解析xml-fatalError", exception);
            }
        });
        String commandPath = xmlPath + "tasks.xml";
        log.info("当前class路径{}...", commandPath);
        Document doc = null;
        try {
            doc = builder.parse(new File(commandPath));
        }
        catch (Exception e) {
            throw new RuntimeException("加载tasks.xml出错", e);
        }
        doc.normalize();
        Element root = doc.getDocumentElement();
        String table = root.getAttribute("table");
        if (StringUtils.isBlank(table)) {
            throw new IllegalArgumentException("task.xml中table不能为空");
        }
        tables = table.split(",|;");

        NodeList propertyNode = root.getElementsByTagName("properties");
        if (propertyNode.getLength() > 0) {
            Element properties = (Element) propertyNode.item(0);
            NodeList propertyList = properties.getElementsByTagName("property");
            int length = propertyList.getLength();
            for (int i = 0; i < length; i++) {
                Element property = (Element) propertyList.item(i);
                String key = property.getAttribute("key");
                String value = property.getAttribute("value");
                if (key.trim().length() == 0) {
                    continue;
                }
                propertiesMap.put(key.trim(), value);
            }
            log.info("加载property完毕");
        }

        NodeList taskList = root.getElementsByTagName("task");
        int length = taskList.getLength();
        for (int i = 0; i < length; i++) {
            Element element = (Element) taskList.item(i);
            String name = element.getAttribute("name");
            String genClass = element.getAttribute("class");
            String template = element.getAttribute("template");
            String suffix = element.getAttribute("suffix");
            String prefix = element.getAttribute("prefix");
            String ext = element.getAttribute("ext");
            String path = element.getAttribute("path");
            if (StringUtils.isBlank(name)) {
                throw new IllegalArgumentException("第" + i + "个task的name不能为空");
            }
            if (StringUtils.isBlank(genClass)) {
                throw new IllegalArgumentException("第" + i + "个task的genClass不能为空");
            }
            if (StringUtils.isBlank(template)) {
                throw new IllegalArgumentException("第" + i + "个task的template不能为空");
            }
            if (StringUtils.isBlank(ext)) {
                throw new IllegalArgumentException("第" + i + "个task的ext不能为空");
            }
            if (StringUtils.isBlank(path)) {
                throw new IllegalArgumentException("第" + i + "个task的path不能为空");
            }

            Map<String, String> map = new LinkedHashMap<String, String>();

            propertyNode = element.getElementsByTagName("property");
            if (propertyNode.getLength() > 0) {
                int propertyLength = propertyNode.getLength();
                for (int k = 0; k < propertyLength; k++) {
                    Element property = (Element) propertyNode.item(k);
                    String key = property.getAttribute("key");
                    String value = property.getAttribute("value");
                    if (key.trim().length() == 0) {
                        continue;
                    }
                    map.put(key.trim(), value);
                }
            }

            Task task = new Task();

            String taskExt = ext.toLowerCase().trim();
            String taskName = name.trim();
            String taskPath = path.trim();
            String taskPrefix = prefix.trim();
            String taskSuffix = suffix.trim();
            String taskTemplate = template.trim();
            String genTask = genClass.trim();

            for (Entry<String, String> entry : propertiesMap.entrySet()) {
                taskExt = taskExt.replace("${" + entry.getKey() + "}", entry.getValue());
                taskName = taskName.replace("${" + entry.getKey() + "}", entry.getValue());
                taskPath = taskPath.replace("${" + entry.getKey() + "}", entry.getValue());
                taskPrefix = taskPrefix.replace("${" + entry.getKey() + "}", entry.getValue());
                taskSuffix = taskSuffix.replace("${" + entry.getKey() + "}", entry.getValue());
                taskTemplate = taskTemplate.replace("${" + entry.getKey() + "}", entry.getValue());
                genTask = genTask.replace("${" + entry.getKey() + "}", entry.getValue());
                for (Entry<String, String> entryMap : map.entrySet()) {
                    entryMap.setValue(entryMap.getValue().replace("${" + entry.getKey() + "}",
                        entry.getValue()));
                }
            }

            try {
                Class<?> clazz = Class.forName(genTask);
                Object object = clazz.newInstance();
                if (!(object instanceof GenerateTask)) {
                    throw new IllegalArgumentException("第" + i + "个task的genClass的类型不正确");
                }
                task.setGenerateTask((GenerateTask) object);
            }
            catch (Exception e) {
                throw new IllegalArgumentException("第" + i + "个task的genClass初始化错误", e);
            }

            task.setExt(taskExt);
            task.setName(taskName);
            task.setPath(taskPath);
            task.setPrefix(taskPrefix);
            task.setProperties(map);
            task.setSuffix(taskSuffix);
            task.setTemplate(taskTemplate);
            taskMap.put(task.getName(), task);

        }
    }
}
